package model.time;

import java.util.Calendar;
import java.util.List;

/**
 * This abstract class defines common structure and protocol for its subclasses.
 * 
 * @author Eric Stoll
 */

public abstract class TimeFrame implements model.search.interfaces.TimeFrame {

	// Structure
	private Calendar dateStart;
	private Calendar dateEnd;
	private Calendar timeStart;
	private Calendar timeEnd;
	private String dayName;

	
	public void print(){
		System.out.println(this.getStringDateStart());
		System.out.println(this.getStringDateEnd());
		System.out.println(this.getStringTimeStart());
		System.out.println(this.getStringTimeEnd());
		System.out.println(this.getStringDay());
		
	}
	
	public String getStringDateStart(){
		return (""+dateStart.get(1)+"/"+(dateStart.get(2)+1)+"/"+dateStart.get(5)+"");
	}
	
	public String getStringDateEnd(){
		return (""+dateEnd.get(1)+"/"+(dateEnd.get(2)+1)+"/"+dateEnd.get(5)+"");
	}
	
	public String getStringTimeStart(){
		return (""+timeStart.get(11)+":"+timeStart.get(12));
	}
	
	public String getStringHourStart(){
		return Integer.toString(timeStart.get(11));
	}
	
	public String getStringMinStart(){
		return Integer.toString(timeStart.get(12));
	}
	
	
	public String getStringTimeEnd(){
		return (""+timeEnd.get(11)+":"+timeEnd.get(12));
	}
	
	public String getStringHourEnd(){
		return Integer.toString(timeEnd.get(11));
	}
	
	public String getStringMinEnd(){
		return Integer.toString(timeEnd.get(12));
	}
	
	public String getStringDay(){
		return dayName;
	}
	
	
	
	// Getters & Setters
	/**
	 * @return GregorianCalendar
	 */
	public Calendar getDateStart() {
		return dateStart;

	}

	/**
	 * Sets the given GregorianCalendar as dateStart
	 * 
	 * @param dateStart
	 */
	public void setDateStart(Calendar dateStart) {
		this.dateStart = dateStart;
	}

	/**
	 * @return GregorianCalendar
	 */
	public Calendar getDateEnd() {
		return dateEnd;
	}

	/**
	 * Sets the given GregorianCalendar as dateEnd
	 * 
	 * @param dateEnd
	 */
	public void setDateEnd(Calendar dateEnd) {
		this.dateEnd = dateEnd;
	}

	/**
	 * Returns a GregorianCalendar with Date default to 1900.01.01 and only
	 * specifying time values.
	 * 
	 * @return GregorianCalendar
	 */
	public Calendar getTimeStart() {
		return timeStart;
	}

	/**
	 * Sets the given GregorianCalendar as the timeStart. This GregorianCalendar
	 * should only specify time values, always setting date to 1900.01.01
	 * 
	 * @param timeStart
	 */
	public void setTimeStart(Calendar timeStart) {
		this.timeStart = timeStart;
	}

	/**
	 * Same scenario as with timeStart
	 * 
	 * @return
	 */
	public Calendar getTimeEnd() {
		return timeEnd;
	}

	/**
	 * Same scenario as with timeStart
	 * 
	 * @param timeEnd
	 */
	public void setTimeEnd(Calendar timeEnd) {
		this.timeEnd = timeEnd;
	}

	/**
	 * String specifying day name
	 * 
	 * @return String
	 */
	public String getDayName() {
		return dayName;
	}

	/**
	 * Sets the given String as dayName
	 * 
	 * @param dayName
	 */
	public void setDayName(String dayName) {
		this.dayName = dayName;
	}

	// Protocol

	/**
	 * Returns True if parameter timeFrame has overlapped timeStart and/or
	 * timeEnd values with this.
	 * 
	 * @param his
	 *            any subclass of TimeFrame
	 * @return Boolean
	 */
	public boolean timeIsOverlapped(TimeFrame his) {
		return ((((this.getTimeStart().after(his.getTimeStart()) || this
				.getTimeStart().equals(his.getTimeStart())) && (this
				.getTimeStart().before(his.getTimeEnd()))) || ((this
				.getTimeEnd().after(his.getTimeStart())) && ((this.getTimeEnd()
				.before(his.getTimeEnd()) || (this.getTimeEnd().equals(his
				.getTimeEnd()))))))
				|| (((his.getTimeStart().after(this.getTimeStart()) || his
						.getTimeStart().equals(this.getTimeStart())) && (his
						.getTimeStart().before(this.getTimeEnd()))) || ((his
						.getTimeEnd().after(this.getTimeStart())) && ((his
						.getTimeEnd().before(this.getTimeEnd()) || (his
						.getTimeEnd().equals(this.getTimeEnd())))))) || (((his
				.getTimeStart().after(this.getTimeStart()) || his
				.getTimeStart().equals(this.getTimeStart())) && (his
				.getTimeEnd().before(this.getTimeEnd()) || his.getTimeEnd()
				.equals(this.getTimeEnd()))) || ((this.getTimeStart().after(
				his.getTimeStart()) || this.getTimeStart().equals(
				his.getTimeStart())) && (this.getTimeEnd().before(
				his.getTimeEnd()) || this.getTimeEnd().equals(his.getTimeEnd())))));
	}

	/**
	 * Returns True if parameter timeFrame has overlapped dateStart and/or
	 * dateEnd values with this.
	 * 
	 * @param his
	 *            any subclass of TimeFrame
	 * @return Boolean
	 */
	public boolean dateRangeIsOverlapped(TimeFrame his) {
		return ((((this.getDateStart().after(his.getDateStart()) || this
				.getDateStart().equals(his.getDateStart())) && (this
				.getDateStart().before(his.getDateEnd()))) || ((this
				.getDateEnd().after(his.getDateStart())) && ((this.getDateEnd()
				.before(his.getDateEnd()) || (this.getDateEnd().equals(his
				.getDateEnd()))))))
				|| (((his.getDateStart().after(this.getDateStart()) || his
						.getDateStart().equals(this.getDateStart())) && (his
						.getDateStart().before(this.getDateEnd()))) || ((his
						.getDateEnd().after(this.getDateStart())) && ((his
						.getDateEnd().before(this.getDateEnd())) || (his
						.getDateEnd().equals(this.getDateEnd()))))) || (((his
				.getDateStart().before(this.getDateStart()) && (his
				.getDateEnd().after(this.getDateEnd())))) || ((this
				.getDateStart().before(his.getDateStart()) && (this
				.getDateEnd().after(his.getDateEnd()))))));
	}

	public boolean isOverlapped(TimeFrame timeFrame)
			throws NullParametersReceivedExpeption, InvalidMinutesException,
			IllegalTimeValuesException {

		if (timeFrame.getClass() == (Object) new SingleTimeFrame(dateEnd,
				dateEnd, dateEnd, dateEnd, dayName))
			return timeFrame.isOverlapped(this);
		else {
			if (timeFrame.getClass() == (Object) new DailyTimeFrame(dateEnd,
					dateEnd, dateEnd, dateEnd))
				return timeFrame.isOverlapped(this);
			else {
				if (timeFrame.getClass() == (Object) new MonthlyTimeFrame(
						dateEnd, dateEnd, dateEnd, dateEnd, dayName))
					return timeFrame.isOverlapped(this);
				else {
					return timeFrame.isOverlapped(this);

				}
			}
		}

	}

	public abstract String getType();

}

/*
 * public boolean isOverlappedWithList(List<TimeFrame> ls, SingleTimeFrame tf) {
 * //itero por cada elemento de la lista y pregunto si this esta solapado.
 * boolean res = false; for (int i = 0; i < ls.size(); i++) { if
 * (ls.get(i).getClass() == SingleTimeFrame.class){ res = res ||
 * tf.isOverlapped((SingleTimeFrame) ls.get(i));} if (ls.get(i).getClass() ==
 * DailyTimeFrame.class){ res = res || tf.isOverlapped((DailyTimeFrame)
 * ls.get(i));} if (ls.get(i).getClass() == WeeklyTimeFrame.class){ res = res ||
 * tf.isOverlapped((WeeklyTimeFrame) ls.get(i));} if (ls.get(i).getClass() ==
 * MonthlyTimeFrame.class){ res = res || tf.isOverlapped((MonthlyTimeFrame)
 * ls.get(i));}
 * 
 * } return res; }
 * 
 * public boolean isOverlappedWithList(List<TimeFrame> ls, DailyTimeFrame tf) {
 * //itero por cada elemento de la lista y pregunto si this esta solapado.
 * boolean res = false; for (int i = 0; i < ls.size(); i++) { if
 * (ls.get(i).getClass() == SingleTimeFrame.class){ res = res ||
 * tf.isOverlapped((SingleTimeFrame) ls.get(i));} if (ls.get(i).getClass() ==
 * DailyTimeFrame.class){ res = res || tf.isOverlapped((DailyTimeFrame)
 * ls.get(i));} if (ls.get(i).getClass() == WeeklyTimeFrame.class){ res = res ||
 * tf.isOverlapped((WeeklyTimeFrame) ls.get(i));} if (ls.get(i).getClass() ==
 * MonthlyTimeFrame.class){ res = res || tf.isOverlapped((MonthlyTimeFrame)
 * ls.get(i));}
 * 
 * } return res; }
 * 
 * public boolean isOverlappedWithList(List<TimeFrame> ls, WeeklyTimeFrame tf) {
 * //itero por cada elemento de la lista y pregunto si this esta solapado.
 * boolean res = false; for (int i = 0; i < ls.size(); i++) { if
 * (ls.get(i).getClass() == SingleTimeFrame.class){ res = res ||
 * tf.isOverlapped((SingleTimeFrame) ls.get(i));} if (ls.get(i).getClass() ==
 * DailyTimeFrame.class){ res = res || tf.isOverlapped((DailyTimeFrame)
 * ls.get(i));} if (ls.get(i).getClass() == WeeklyTimeFrame.class){ res = res ||
 * tf.isOverlapped((WeeklyTimeFrame) ls.get(i));} if (ls.get(i).getClass() ==
 * MonthlyTimeFrame.class){ res = res || tf.isOverlapped((MonthlyTimeFrame)
 * ls.get(i));}
 * 
 * } return res; }
 * 
 * public boolean isOverlappedWithList(List<TimeFrame> ls, MonthlyTimeFrame tf)
 * { //itero por cada elemento de la lista y pregunto si this esta solapado.
 * boolean res = false; for (int i = 0; i < ls.size(); i++) { if
 * (ls.get(i).getClass() == SingleTimeFrame.class){ res = res ||
 * tf.isOverlapped((SingleTimeFrame) ls.get(i));} if (ls.get(i).getClass() ==
 * DailyTimeFrame.class){ res = res || tf.isOverlapped((DailyTimeFrame)
 * ls.get(i));} if (ls.get(i).getClass() == WeeklyTimeFrame.class){ res = res ||
 * tf.isOverlapped((WeeklyTimeFrame) ls.get(i));} if (ls.get(i).getClass() ==
 * MonthlyTimeFrame.class){ res = res || tf.isOverlapped((MonthlyTimeFrame)
 * ls.get(i));}
 * 
 * } return res; }
 */

